/*
 * @Author: xiaosihan 
 * @Date: 2023-05-31 18:27:16 
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2024-03-13 11:19:36
 */


//Group
import { get, has, uniq } from "lodash";
import { autorun, toJS } from "mobx";
import { BufferGeometry, Euler, Group, InstancedBufferAttribute, InstancedMesh, Matrix4, Mesh, MeshBasicMaterial, MeshLambertMaterial, Object3D, Quaternion, Vector3 } from "three";
import threeLoader from "three-base/threeLoader";
import threeUtils from "three-base/threeUtils";
import { degToRad } from "three/src/math/MathUtils";
import InstancedGroupMesh from "three-base/InstancedMeshBase";
import MeshBase from "three-base/MeshBase";
import { DeviceData } from "@/types/type";

// 其他设备分组
export default class DeviceGroup extends Group {
    constructor() {
        super();
    }

    static _position: Vector3 = new Vector3();
    static _scale: Vector3 = new Vector3(1, 1, 1);
    static _rotation: Euler = new Euler();
    static _Quaternion: Quaternion = new Quaternion();
    static _Matrix4: Matrix4 = new Matrix4();

    // declare children: Array<OtherDevice>;

    type = "deviceGroup";

    //实例模型组
    group = (() => {
        const group = new class InstanceGroup extends Group {
            constructor() {
                super();
            }
            //实例模型组
            declare children: Array<InstancedGroupMesh>;
        }();

        this.add(group);
        return group;
    })();

    //需要替换贴图的模型组
    mapMeshGroup = (() => {
        const mapMeshGroup = new class MapMeshGroup extends Group {

            // 创建模型
            creatMesh(id: string, geo: BufferGeometry, map: string) {
                const mapMesh = this.children.find(o => o.uuid === id);
                const texture = threeLoader.getTexture(map);
                texture.flipY = false;

                if (mapMesh) {
                    ((mapMesh as Mesh).material as MeshBasicMaterial).map = texture;
                    return mapMesh;
                } else {
                    const mapMesh = new Mesh(geo, new MeshBasicMaterial({ map: texture }));
                    this.add(mapMesh);
                    return mapMesh;
                }
            }

            // 先隐藏全部
            hideAll() {
                this.children.map(o => o.visible = false);
            }

        }
        this.add(mapMeshGroup);
        return mapMeshGroup;
    })();

    //加载中的模型
    loaddingUrl: Array<string> = [];

    //根据url 获取实例模型组  url
    async getInstanceMeshGroupByUrl(url: string): Promise<InstancedGroupMesh> {
        let instanceMeshGroup = this.group.children.find(o => o.url === url)!;
        if (!this.loaddingUrl.includes(url) && !instanceMeshGroup) {
            this.loaddingUrl.push(url);
            // const meshBase = new MeshBase(url);
            // await new Promise<void>((resolve, reject) => {
            //     meshBase.addEventListener("loaded", () => {
            //         meshBase.traverseMesh(mesh => {
            //             const { color, map, transparent, opacity, alphaTest, side } = mesh.material as MeshBasicMaterial;
            //             mesh.material = new MeshLambertMaterial({ color, map, transparent, opacity, alphaTest: 0.2, side });
            //             if (!mesh.geometry.getAttribute("normal")) {
            //                 mesh.geometry.computeVertexNormals();
            //             }
            //         });
            //         resolve();
            //     });
            // });

            // threeUtils.center(meshBase);
            // threeUtils.alignBottom(meshBase);

            instanceMeshGroup = new InstancedGroupMesh(url);
            instanceMeshGroup.url = url;

            this.group.add(instanceMeshGroup);

            this.loaddingUrl = this.loaddingUrl.filter(u => u !== url);

            return instanceMeshGroup;

        } else if (this.loaddingUrl.includes(url) && !instanceMeshGroup) {
            while (this.loaddingUrl.includes(url)) {
                await new Promise(resolve => setTimeout(resolve, 50));
            }
        }

        return this.group.children.find(o => o.url === url)!;
    }

    //缩放值为0 的矩阵 隐藏模型使用
    hideMatrix4 = new Matrix4(
        0, 0, 0, 0,
        0, 0, 0, 0,
        0, 0, 0, 0,
        0, 0, 0, 0
    );

    // 临时保存arrayBuffer对饮的blob 地址
    arrayBufferMap = new Map<ArrayBuffer, string>();

    // 设置数据
    async setDeviceDatas(deviceDatas: Array<DeviceData>) {

        //按照url 分组
        const urls = uniq(deviceDatas.map(d => d.url));

        //显示有效的其他设备
        this.group.children.map(o => o.visible = urls.includes(o.url));

        // 先隐藏所有需要替换贴图的模型
        this.mapMeshGroup.hideAll();

        // 遍历 url
        for (let url of urls) {
            const modelDatasWithUrl = deviceDatas.filter(d => d.url === url);
            // 按照 url来获取 InstanceMeshGroup 对象
            const instanceMeshGroup = this.group.children.find(o => o.url === url) || (await this.getInstanceMeshGroupByUrl(url));

            //three事件
            instanceMeshGroup.userData = {
                cursor: "pointer",
                enableEvent: true,
            };
            instanceMeshGroup.addEventListener("click", e => {
                // console.log(url, e.instanceId);
                const targetData = deviceDatas.filter(d => d.url === url)[e.instanceId];
                // console.log(targetData);
                this.dispatchEvent({ type: "click", data: targetData } as never);
            });

            // 如果实例数量不对 就需要创建新的实例矩阵
            if (modelDatasWithUrl.length !== instanceMeshGroup.count) {
                instanceMeshGroup.count = modelDatasWithUrl.length;
                instanceMeshGroup.children.map((instanceMesh: InstancedMesh) => {
                    instanceMesh.instanceMatrix = new InstancedBufferAttribute(new Float32Array(modelDatasWithUrl.length * 16), 16);
                    instanceMesh.count = instanceMeshGroup.count;
                    instanceMesh.castShadow = true; // 创建阴影

                });
            }

            for (let i = 0; i < modelDatasWithUrl.length; i++) {

                // 设置矩阵
                DeviceGroup._position.set(modelDatasWithUrl[i].x, modelDatasWithUrl[i].y, modelDatasWithUrl[i].z);
                DeviceGroup._rotation.set(
                    degToRad(modelDatasWithUrl[i].phi),
                    degToRad(modelDatasWithUrl[i].theta),
                    degToRad(modelDatasWithUrl[i].pitch)
                );
                DeviceGroup._Quaternion.setFromEuler(DeviceGroup._rotation);

                DeviceGroup._Matrix4.compose(DeviceGroup._position, DeviceGroup._Quaternion, DeviceGroup._scale);
                instanceMeshGroup.setMatrixAt(i, DeviceGroup._Matrix4);

                //如果有模型需要替换贴图的就隐藏这个模型
                instanceMeshGroup.children.map((instancedMesh: InstancedMesh) => {

                    //如果贴图是个图片地址
                    if (has(modelDatasWithUrl, [i, "map", instancedMesh.name])) {
                        instancedMesh.setMatrixAt(i, this.hideMatrix4);
                        const { id } = modelDatasWithUrl[i];
                        const mapMesh = this.mapMeshGroup.creatMesh(
                            `${id}_${instancedMesh.name}`,
                            instancedMesh.geometry,
                            get(modelDatasWithUrl, [i, "map", instancedMesh.name], "")
                        );
                        mapMesh.uuid = `${id}_${instancedMesh.name}`;
                        mapMesh.visible = true;
                        mapMesh.position.copy(DeviceGroup._position);
                        mapMesh.rotation.copy(DeviceGroup._rotation);

                        //如果图片是个字节数组
                    } else if (has(modelDatasWithUrl, [i, "map", `${instancedMesh.name}ByteArray`])) {

                        const arrayBuffer = get(modelDatasWithUrl, [i, "map", `${instancedMesh.name}ByteArray`]);

                        if (!this.arrayBufferMap.has(arrayBuffer)) {
                            // 使用Uint8Array创建一个Blob对象  
                            let blob = new Blob([arrayBuffer], { type: 'image/png' });

                            // 创建一个指向Blob的URL  
                            let blobUrl = URL.createObjectURL(blob);

                            this.arrayBufferMap.set(arrayBuffer, blobUrl);

                            let img = document.createElement('img');
                            img.src = blobUrl;
                            document.body.appendChild(img); // 将图片添加到页面中
                        }

                        const blobUrl = this.arrayBufferMap.get(arrayBuffer)!;

                        instancedMesh.setMatrixAt(i, this.hideMatrix4);
                        const { id } = modelDatasWithUrl[i];
                        const mapMesh = this.mapMeshGroup.creatMesh(
                            `${id}_${instancedMesh.name}`,
                            instancedMesh.geometry,
                            blobUrl
                        );
                        mapMesh.uuid = `${id}_${instancedMesh.name}`;
                        mapMesh.visible = true;
                        mapMesh.position.copy(DeviceGroup._position);
                        mapMesh.rotation.copy(DeviceGroup._rotation);

                    }

                })
            }
        }
    }

    //     const { inFloorId, editorOtherDeviceId, lookOtherDeviceId, hoverOtherDeviceId } = computerRoom3DStore;
    //     const hides = toJS(computerRoom3DStore.hides);
    //     const otherDeviceDatas = toJS(computerRoom3DStore.otherDeviceDatas).filter(data => data.floorId === inFloorId && !hides.some(hide => (hide.type === data.type && hide.id === data.id)));

    //     //按照url 分组
    //     const urls = uniq(otherDeviceDatas.map(d => d.url));

    //     //显示有效的其他设备
    //     this.group.children.map(o => o.visible = urls.includes(o.url));

    //     // 先隐藏所有需要替换贴图的模型
    //     this.mapMeshGroup.hideAll();

    //     // 遍历 url
    //     for (let url of urls) {
    //         const modelDatasWithUrl = otherDeviceDatas.filter(d => d.url === url);
    //         // 按照 url来获取 InstanceMeshGroup 对象
    //         const instanceMeshGroup = this.group.children.find(o => o.url === url) || (await this.getInstanceMeshGroupByUrl(url));

    //         // 如果实例数量不对 就需要创建新的实例矩阵
    //         if (modelDatasWithUrl.length !== instanceMeshGroup.count) {
    //             instanceMeshGroup.count = modelDatasWithUrl.length;
    //             instanceMeshGroup.children.map((instanceMesh: InstancedMesh) => {
    //                 instanceMesh.instanceMatrix = new InstancedBufferAttribute(new Float32Array(modelDatasWithUrl.length * 16), 16);
    //                 instanceMesh.count = instanceMeshGroup.count;
    //                 instanceMesh.castShadow = true; // 创建阴影
    //             });
    //         }

    //         for (let i = 0; i < modelDatasWithUrl.length; i++) {

    //             // 设置矩阵
    //             DeviceGroup._position.set(modelDatasWithUrl[i].x, modelDatasWithUrl[i].y, modelDatasWithUrl[i].z);
    //             DeviceGroup._rotation.set(
    //                 degToRad(modelDatasWithUrl[i].phi),
    //                 degToRad(modelDatasWithUrl[i].theta),
    //                 degToRad(modelDatasWithUrl[i].pitch)
    //             );
    //             DeviceGroup._Quaternion.setFromEuler(DeviceGroup._rotation);

    //             // 只显示当前进入的那层楼的模型
    //             const sclae = (modelDatasWithUrl[i].floorId === inFloorId) ? 1 : 0;
    //             DeviceGroup._scale.set(sclae, sclae, sclae);

    //             DeviceGroup._Matrix4.compose(DeviceGroup._position, DeviceGroup._Quaternion, DeviceGroup._scale);
    //             instanceMeshGroup.setMatrixAt(i, DeviceGroup._Matrix4);

    //             //如果有模型需要替换贴图的就隐藏这个模型
    //             instanceMeshGroup.children.map((instancedMesh: InstancedMesh) => {

    //                 //如果贴图是个图片地址
    //                 if (has(modelDatasWithUrl, [i, "map", instancedMesh.name])) {
    //                     instancedMesh.setMatrixAt(i, this.hideMatrix4);
    //                     const { id } = modelDatasWithUrl[i];
    //                     const mapMesh = this.mapMeshGroup.creatMesh(
    //                         `${id}_${instancedMesh.name}`,
    //                         instancedMesh.geometry,
    //                         get(modelDatasWithUrl, [i, "map", instancedMesh.name], "")
    //                     );
    //                     mapMesh.uuid = `${id}_${instancedMesh.name}`;
    //                     mapMesh.visible = true;
    //                     mapMesh.position.copy(DeviceGroup._position);
    //                     mapMesh.rotation.copy(DeviceGroup._rotation);

    //                     //如果图片是个字节数组
    //                 } else if (has(modelDatasWithUrl, [i, "map", `${instancedMesh.name}ByteArray`])) {

    //                     const arrayBuffer = get(modelDatasWithUrl, [i, "map", `${instancedMesh.name}ByteArray`]);

    //                     if (!this.arrayBufferMap.has(arrayBuffer)) {
    //                         // 使用Uint8Array创建一个Blob对象  
    //                         let blob = new Blob([arrayBuffer], { type: 'image/png' });

    //                         // 创建一个指向Blob的URL  
    //                         let blobUrl = URL.createObjectURL(blob);

    //                         this.arrayBufferMap.set(arrayBuffer, blobUrl);

    //                         let img = document.createElement('img');
    //                         img.src = blobUrl;
    //                         document.body.appendChild(img); // 将图片添加到页面中
    //                     }

    //                     const blobUrl = this.arrayBufferMap.get(arrayBuffer)!;

    //                     instancedMesh.setMatrixAt(i, this.hideMatrix4);
    //                     const { id } = modelDatasWithUrl[i];
    //                     const mapMesh = this.mapMeshGroup.creatMesh(
    //                         `${id}_${instancedMesh.name}`,
    //                         instancedMesh.geometry,
    //                         blobUrl
    //                     );
    //                     mapMesh.uuid = `${id}_${instancedMesh.name}`;
    //                     mapMesh.visible = true;
    //                     mapMesh.position.copy(DeviceGroup._position);
    //                     mapMesh.rotation.copy(DeviceGroup._rotation);

    //                 }

    //             })

    //             //选中的线框
    //             if ([lookOtherDeviceId].includes(modelDatasWithUrl[i].id)) {
    //                 const { x, y, z } = modelDatasWithUrl[i];
    //                 this.boxLine2.setSize(instanceMeshGroup.size);
    //                 this.boxLine2.position.set(x, y + instanceMeshGroup.size.y / 2, z);
    //                 this.boxLine2.rotation.copy(DeviceGroup._rotation);
    //             }

    //             //鼠标滑过的线框
    //             if ([hoverOtherDeviceId].includes(modelDatasWithUrl[i].id)) {
    //                 const { x, y, z } = modelDatasWithUrl[i];
    //                 this.hoverBoxLine2.setSize(instanceMeshGroup.size);
    //                 this.hoverBoxLine2.position.set(x, y + instanceMeshGroup.size.y / 2, z);
    //                 this.hoverBoxLine2.rotation.copy(DeviceGroup._rotation);
    //             }

    //         }
    //     }


    //     // 创建点击模型盒的实例矩阵
    //     if (otherDeviceDatas.length !== this.modelEventBox.count) {
    //         this.modelEventBox.count = otherDeviceDatas.length;
    //         this.modelEventBox.instanceMatrix = new InstancedBufferAttribute(new Float32Array(otherDeviceDatas.length * 16), 16);
    //     }

    //     //设置点击模型盒的矩阵
    //     for (let i = 0; i < otherDeviceDatas.length; i++) {
    //         // 设置矩阵
    //         DeviceGroup._position.set(otherDeviceDatas[i].x, otherDeviceDatas[i].y, otherDeviceDatas[i].z);
    //         const instanceMeshGroup = await this.getInstanceMeshGroupByUrl(otherDeviceDatas[i].url);

    //         // 只显示当前进入的那层楼的模型
    //         if (otherDeviceDatas[i].floorId === inFloorId) {
    //             DeviceGroup._scale.copy(instanceMeshGroup.size);
    //         } else {
    //             DeviceGroup._scale.set(0, 0, 0);
    //         }

    //         DeviceGroup._rotation.set(
    //             degToRad(otherDeviceDatas[i].phi),
    //             degToRad(otherDeviceDatas[i].theta),
    //             degToRad(otherDeviceDatas[i].pitch)
    //         );
    //         DeviceGroup._Quaternion.setFromEuler(DeviceGroup._rotation);

    //         DeviceGroup._Matrix4.compose(DeviceGroup._position, DeviceGroup._Quaternion, DeviceGroup._scale);
    //         this.modelEventBox.setMatrixAt(i, DeviceGroup._Matrix4);
    //     }
    //     this.modelEventBox.instanceMatrix.needsUpdate = true;
    //     this.modelEventBox.computeBoundingSphere();
    //     Object.assign(this.modelEventBox.userData, {
    //         enableEvent: !editorOtherDeviceId
    //     });

    // });

    //绑定其他设备的事件
    bindEvent(object3d: Object3D) {
        object3d.addEventListener("leftclick", (e: any) => {
            console.log("点击了其他设备", e);
            // const { editorOtherDeviceId } = computerRoom3DStore;
            // if (editorOtherDeviceId) {
            //     computerRoom3DStore.setEditorOtherDeviceId("");
            // }
        });

    }

}
